iT邦幫忙

2024 iThome 鐵人賽

DAY 11
0
Python

在AWS上進行物聯網與人工智慧實作系列 第 11

D11-使用 MicroPython 連接 Wi-Fi、同步 NTP

  • 分享至 

  • xImage
  •  

使用 MicroPython 連接 Wi-Fi、同步 NTP

目錄

network — 網路配置

本模組提供了特定硬體的網路驅動程序,用於配置硬體網路接口。然後,可以通過 usocket 模組使用已配置接口提供的網路服務。

函數
network.phy_mode([mode])
配置PHY模式。定義的模式常數如下:
mode

  • MODE_11B -- IEEE 802.11b,1
  • MODE_11G -- IEEE 802.11g,2
  • MODE_11N -- IEEE 802.11n,4

network.WLAN(interface_id)
新增 WLAN 網路接口物件。

interface_id

  • network.STA_IF 站點也稱為客戶端,連接到上游Wi-Fi接入點
  • network.AP_IF 作為熱點,允許其他Wi-Fi客戶端接入。熱點模式允許用戶將自己的設備配置為熱點,這讓多個設備之間的無線連接在不借助外部路由器網路的情況下成為可能。

WLAN.active(is_active)
帶有參數時,為是否啟用,不帶參數為查詢當前狀態。當啟用Wi-Fi功能後,功耗會增加。當不使用Wi-Fi功能可使用 active 來真正關閉物理層的無線網路。

is_active

  • True 啟用網路接口
  • False 停用網路接口

WLAN.connect(ssid, password)
使用指定的密碼連接到指定的無線網路

  • ssid:Wi-Fi名稱
  • password:Wi-Fi密碼

WLAN.disconnect()
斷開當前連接的無線網路。

WLAN.status()
返回無線連接的當前狀態。

  • STAT_IDLE -- 沒有連接,沒有活動-1000
  • STAT_CONNECTING -- 正在連接-1001
  • STAT_WRONG_PASSWORD -- 由於密碼錯誤而失敗-202
  • STAT_NO_AP_FOUND -- 失敗,因為沒有接入點回復,201
  • STAT_GOT_IP -- 連接成功-1010
  • STAT_ASSOC_FAIL -- 203
  • STAT_BEACON_TIMEOUT -- 逾時-200
  • STAT_HANDSHAKE_TIMEOUT -- 握手逾時-204

WLAN.isconnected()
在STA模式下,如果連接到Wi-Fi接入點並具有有效的IP地址則返回True,否則返回False。
在AP模式下,當站點連接時返回True,否則返回False。

WLAN.ifconfig([(ip, subnet, gateway, dns)])
不帶參數時,返回一個4元組(ip, subnet_mask, gateway, DNS_server);帶參數時,配置靜態IP。

  • ip:IP地址
  • subnet_mask:子網遮罩
  • gateway:閘道
  • DNS_server:DNS服務器

wlan.config('param')
wlan.config(param=value, ...)
獲取或配置常規網路接口參數。這些方法允許使用超出標準IP配置的其他參數(如所處理 wlan.ifconfig() )。 這些包括特定於網路和硬體的參數。對於配置參數,應使用關鍵字參數語法,可以一次配置多個參數。

param value
mac MAC address (bytes)
essid Wi-Fi access point name (string)
channel Wi-Fi channel (integer)
hidden Whether ESSID is hidden (boolean)
authmode Authentication mode supported (enumeration, see module constants)
password Access password (string)

原始代碼

# enable station interface and connect to Wi-Fi access point
import network
import binascii

wlan = network.WLAN(network.STA_IF)
wlan.active(True)
if not wlan.isconnected():
    print('connecting to network...')
    wlan.connect('your-ssid', 'your-password')
    while not wlan.isconnected():
        pass
print('network config: ', wlan.ifconfig())
print('MAC Address: ',binascii.hexlify(wlan.config('mac')).decode())
wlan.disconnect()

輸出結果為:

connecting to network...
network config:  ('192.168.233.160', '255.255.255.0', '192.168.233.106', '192.168.233.106')
MAC Address:  08b61f283b60

time – 時間相關功能

time 模組提供獲取當前時間和日期、測量時間間隔和延遲的函數。時間紀元(Time Epoch): Unix 設備使用 1970-01-01 00:00:00 UTC 的 POSIX 系統紀元標準。但是,嵌入式設備使用 2000-01-01 00:00:00 UTC 的紀元。
維護實際日曆日期/時間需要即時時鐘 (RTC)。在具有底層作業系統(包括某些 RTOS)的系統上,RTC 可能是隱式的。配置和維護實際日曆時間是 OS/RTOS 的責任,是在 MicroPython 之外完成的,它只是使用 OS API 來查詢日期/時間。然而,在裸機端口上,系統時間取決於machine.RTC()物件。當前日曆時間可通過 machine.RTC().datetime(tuple) 函數配置。
在嵌入系統中,通常通過以下方式維護時間:

  • 通過備用電池(可能是特定板的附加可選組件)。
  • 使用網路時間協議(需要由端口/用戶配置)。
  • 由用戶在每次供電時手動配置(許多板在硬復位後保持 RTC 時間,儘管在這種情況下有些可能需要再次配置)。

time.time()
以整數形式返回自 Epoch 以來的秒數,但因為 ESP32-CAM 並有沒有電池,所以每次開機的預設時間為 2000-01-01 00:00:00 UTC。如果想開發可移植的 MicroPython 應用程序,不應該依賴這個函數來提供系統日期,建議使用網路時間協議(Network Time Protocol, NTP)。如果需要更高的精度,請使用 time_ns(),如果可以接受相對時間,則使用 ticks_ms() 和 ticks_us() 函數。

time.time_ns()
類似於time()但返回自 Epoch 以來的納秒,為一個整數。

time.ticks_ms()
返回帶有任意參考點的遞增毫秒計數器,為一個整數。

time.ticks_us()
就像 ticks_ms()上面一樣,但以微秒為單位。

正常來說 ESP32-CAM 並沒有配置電池,所以每次連接到電腦時,ESP32-CAM 的時間應該是 2000-01-01 00:00:00 UTC,然而,我們是使用 Thonny 來進行開發 ESP32-CAM,所以如果要觀察沒經過調整後的時間,必需把 Thonny 的自動配置時間功能關閉,如下圖所示。

https://ithelp.ithome.com.tw/upload/images/20240818/20129510YMymZvYATn.png
圖 1. 在 Thonny 選項中,關閉為裝置的 RTC 同步時間

import time
time.time()
time.time_ns()
time.ticks_ms()
time.ticks_us()

輸出結果顯示,從為 ESP32-CAM 供電,到執行這段程式的時間為 13 秒:

13
13336137000
13335
13343443

time.gmtime([secs])
time.localtime([secs])
將自 Epoch以來以秒錶示的時間秒,轉換為一個 8 元組,其中包含: (year, month, mday, hour, minute, second, weekday, yearday)

該 gmtime()函數以 UTClocaltime() 返回日期時間元組,並以本地時間返回日期時間元組。

8元組中條目的格式為:

  • 年份包括世紀(例如 2014)。
  • 月份是 1-12
  • mday 是 1-31
  • 小時是 0-23
  • 分鐘是 0-59
  • second is 0-59
  • 週一至周日是 0-6
  • 年日是 1-366

以下代碼為取得目前時間,因為 ESP32-CAM 無法持續維護時間,所以得到的時間預設為為自 2000 年 1 月 1 日以來的開機秒數。

參考代碼

import time
localtime = time.localtime(time.time())
print("localtime :", localtime)
gmtime = time.gmtime(time.time())
print("gmtime :", gmtime)

輸出結果為:

localtime : (2000, 1, 1, 0, 2, 14, 5, 1)
gmtime : (2000, 1, 1, 0, 2, 14, 5, 1)

time.mktime()
這是本地時間的反函數。它的參數是一個完整的 8 元組,表示按照本地時間的時間格式。會返回一個整數,它是自 2000 年 1 月 1 日以來的秒數。以下參考代碼是利用 mktime 函數生成指定日期的秒數,再透過 machine.RTC().datetime 設定系統時間。

import time, machine
# 指定特定時間,格式為 (year, month, mday, hour, minute, second, weekday, yearday)
tup = (2023, 3, 1, 19, 18, 26, 2, 60) 
setupTime = time.mktime(tup)
print("localtime :", time.localtime(setupTime))
# 將特定時間寫入硬體 RTC 中,格式為  (year, month, day, weekday, hours, minutes, seconds, subseconds)
timeforRTC = (2023, 3, 1, 2, 19, 18, 26, 0) 
machine.RTC().datetime(timeforRTC)
print("localtime :", time.localtime(time.time()))

輸出結果為:

localtime : (2023, 3, 1, 19, 18, 26, 2, 60)
localtime : (2023, 3, 1, 19, 18, 26, 2, 60)

time.sleep(seconds)
睡眠給定的秒數。某些板可能接受秒作為浮點數以休眠幾秒鐘。請注意,為了與它們的使用sleep_ms()和 sleep_us() 功能兼容,其他板可能不接受浮點參數。

time.sleep_ms(ms)
給定毫秒數的延遲,應為正數或 0。此函數將延遲至少給定的毫秒數,但如果必須進行其他處理,例如中斷處理程序或其他線程,則可能需要更長的時間。

time.sleep_us(us)
給定微秒數的延遲,應為正數或 0。

參考代碼

import time
print("Now : (ms)", time.ticks_ms())
# 等待 1 秒
time.sleep(1)
print("Now : (ms)", time.ticks_ms())
# 等待 10 毫秒(1/1000秒)
time.sleep_ms(10)
print("Now : (ms)", time.ticks_ms())

輸出結果為:

Now : (ms) 2787980
Now : (ms) 2788981
Now : (ms) 2788991

ntptime - 時間同步

該模組用於時間同步,提供準確時間,國際標準時間(UTC)。
Network Time Protocol(NTP)是用來使計算機時間同步化的一種協議,它可以使計算機對其服務器或時鐘源(如石英鐘,GPS等等)做同步化。它可以提供高精准度的時間校正。

ntptime.settime()
同步時間服務器的國際標準時間。

ntptime.host
時間服務器,預設時間服務器為"pool.ntp.org"
台灣可用的 ntp server 如下:

  • tock.stdtime.gov.tw
  • watch.stdtime.gov.tw
  • time.stdtime.gov.tw
  • clock.stdtime.gov.tw
  • tick.stdtime.gov.tw

示例中先連上指定的 Wi-Fi,取得網路連線,接著時間服務器,接著 ESP32-CAM 同步時間服務器的時間,接著再設定時區時間。

import time, network, ntptime
import machine
print("同步前本地時間:%s" %str(time.localtime()))
# connect to Wi-Fi
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect('your-ssid', 'your-password')
while not wlan.isconnected():
    pass
print('connected')

ntptime.host = 'time.stdtime.gov.tw'
ntptime.settime()
print("同步後 UTC 時間:%s" %str(time.localtime()))
taipei_timezone = 8
(year, month, day, hour, minute, second, weekday, yearday) = time.gmtime(time.time())
timeforRTC = (year, month, day, weekday, hour + taipei_timezone, minute, second, 0) 
machine.RTC().datetime(timeforRTC)
print("根據時間調整後的本地時間:%s" %str(time.localtime()))

輸出結果為:

同步前本地時間:(2000, 1, 1, 0, 0, 29, 5, 1)
connected
同步後 UTC 時間:(2024, 8, 11, 8, 54, 22, 6, 224)
根據時間調整後的本地時間:(2024, 8, 11, 16, 54, 22, 6, 224)

參考資料


上一篇
D10-使用 MicroPython 控制燈號、撰寫 ISR - machine
下一篇
D12-使用 MicroPython 安裝新模組與使用
系列文
在AWS上進行物聯網與人工智慧實作30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言